﻿using System;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
using DesktopClient.Controls;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;
using Microsoft.DirectX.DirectInput;
using MultiResolutioning.Algorithms;
using MultiResolutioning.Data;
using MultiResolutioning.Files;
using MultiResolutioning.Structures;
using System.IO;
using System.Collections.Generic;
using System.Diagnostics;
using System.Collections;

namespace DesktopClient
{
	public partial class MainForm : Form
	{
		#region Enums

		private enum AdditionalDisplay
		{
			None,
			Wireframe,
			Points
		}

		#endregion

		#region Fields

		#region Consts

		private readonly Vector3 vUp = new Vector3(0, 1, 0);
		private readonly Vector3 vZ = new Vector3(0, 0, 1);

		#endregion

		#region CustomControls

		private DoubleBufferedPanel canvas;

		#endregion

		#region Display options & control flags

		private bool faces;
		private AdditionalDisplay displayOption = AdditionalDisplay.None;
		private bool panelhover = false;

		#endregion

		#region DirectX presentation elements

		private Microsoft.DirectX.Direct3D.Device device;
		private Microsoft.DirectX.DirectInput.Device mouse;
		private Vector3 eyePoint;
		private Vector3 modelCenter;
		private Quaternion modelQuaternion = Quaternion.Identity;
		private CustomVertex.PositionNormal[] vertices;
		private CustomVertex.PositionColored[] normals;
		private VertexBuffer vb;
		private VertexBuffer vertexNormals;
		private Material material = new Material();

		#endregion

		#region Progressive mesh elements

		private ProgressiveMesh progressive;
		private MeshData mesh;
		private int downloadedSplits = 0;
		private int facesCount;

		#endregion

		#endregion

		#region Constructors

		public MainForm()
		{
			InitializeComponent();
			
			// Canvas setting.
			canvas = new DoubleBufferedPanel();
			canvas.Size = new System.Drawing.Size(500, 500);
			canvas.MouseEnter += (object sender, EventArgs e) => { this.panelhover = true; };
			canvas.MouseLeave += (object sender, EventArgs e) => { this.panelhover = false; };

			this.Controls.Add(canvas);
			InitializeDevice();
			InitMouse();

			ddlDisplayOptions.SelectedIndex = 0;
			ddlShade.SelectedIndex = 0;
			ddlAlgotithm.SelectedIndex = 0;

			material.Diffuse = Color.Gray;
			material.Specular = Color.White;
			material.SpecularSharpness = 15.0f;

			faces = cbFaces.Checked;
		}

		#endregion

		#region Initializations

		private void InitializeDevice()
		{
			var presentParams = new PresentParameters
			{
				Windowed = true,
				SwapEffect = SwapEffect.Discard
			};

			presentParams.AutoDepthStencilFormat = DepthFormat.D16;
			presentParams.EnableAutoDepthStencil = true;
			presentParams.PresentationInterval = PresentInterval.Default;

			device = new Microsoft.DirectX.Direct3D.Device(0,
								Microsoft.DirectX.Direct3D.DeviceType.Hardware,
								canvas,
								CreateFlags.HardwareVertexProcessing,
								presentParams);

			ConfigureDevice();
		}

		private void ConfigureDevice()
		{
			device.RenderState.CullMode = Cull.None;
			device.RenderState.FillMode = FillMode.Solid;

			device.RenderState.ShadeMode = ShadeMode.Flat;
			device.RenderState.Lighting = true;
			device.RenderState.SpecularEnable = true;
			device.Lights[0].Type = LightType.Directional;
			device.Lights[0].Diffuse = Color.White;
			device.Lights[0].Specular = Color.White;
			device.Lights[0].Direction = new Vector3(-1.5f, -1, -1f);
			device.Lights[0].Enabled = true;

			device.Material = this.material;
		}

		private void InitMouse()
		{
			mouse = new Microsoft.DirectX.DirectInput.Device(SystemGuid.Mouse);
			mouse.SetDataFormat(DeviceDataFormat.Mouse);
			mouse.SetCooperativeLevel(this, CooperativeLevelFlags.Background | CooperativeLevelFlags.NonExclusive);
			mouse.Properties.AxisModeAbsolute = false;
			mouse.Acquire();
		}

		#endregion

		#region Buffers Declarations

		private void VertexDeclaration(bool faceNormal)
		{
			if (this.mesh == null)
				return;
			var notRemoved = mesh.faces.Where(x => x.removed == false).ToList();
			this.facesCount = notRemoved.Count;
			vb = new VertexBuffer(typeof(CustomVertex.PositionNormal), facesCount * 3, device, Usage.Dynamic | Usage.WriteOnly, CustomVertex.PositionNormal.Format, Pool.Default);
			
			vertices = new CustomVertex.PositionNormal[facesCount * 3];
			Vertex temp;

			if (faceNormal)
			{
				for (int i = 0; i < facesCount * 3; ++i)
				{
					temp = notRemoved[i / 3].vertices[i % 3];
					vertices[i].Position = temp.position;
					vertices[i].Normal = notRemoved[i / 3].normal;
				}
			}
			else
			{
				for (int i = 0; i < facesCount * 3; ++i)
				{
					temp = notRemoved[i / 3].vertices[i % 3];
					vertices[i].Position = temp.position;
					vertices[i].Normal = temp.normal;
				}
			}
			
			vb.SetData(vertices, 0, LockFlags.None);


			//NormalsDeclaration();
		}

		private void NormalsDeclaration()
		{
			vertexNormals = new VertexBuffer(typeof(CustomVertex.PositionColored), mesh.vertices.Count * 2, device, Usage.Dynamic | Usage.WriteOnly, CustomVertex.PositionColored.Format, Pool.Default);

			normals = new CustomVertex.PositionColored[mesh.vertices.Count * 2];

			for (int i = 0; i < mesh.vertices.Count; ++i)
			{
				int tempIterator = i * 2;
				normals[tempIterator].Position = mesh.vertices[i].position;
				normals[tempIterator].Color = Color.Red.ToArgb();

				++tempIterator;
				normals[tempIterator].Position = (1 * mesh.vertices[i].normal + mesh.vertices[i].position);
				normals[tempIterator].Color = Color.Red.ToArgb();


			}

			vertexNormals.SetData(normals, 0, LockFlags.None);
		}

		#endregion

		#region Camera operations

		private void Zoom(int p)
		{
			Matrix view = device.Transform.View;
			view = view * Matrix.Translation(0, 0, (p * eyePoint.Length()) * 0.02f);

			device.Transform.View = view;
		}

		private void RotateModel(int X, int Y)
		{
			modelQuaternion.Multiply(Quaternion.RotationAxis(vUp, (float)X / 200));
			modelQuaternion.Multiply(Quaternion.RotationAxis(vZ, (float)Y / 200));
		}

		private void CameraPositioning()
		{
			ResetView();
			ConfigureDevice();
		}
		
		private void ResetView()
		{
			float ymax, ymin, zmax, zmin, xmin, xmax;

			Vertex current = mesh.vertices[0];
			ymax = ymin = current.position.Y;
			zmax = zmin = current.position.Z;
			xmin = xmax = current.position.X;

			for (int j = 1; j < progressive.mesh.vertices.Count; ++j)
			{
				current = progressive.mesh.vertices[j];

				if (current.position.Y < ymin)
					ymin = current.position.Y;
				else if (current.position.Y > ymax)
					ymax = current.position.Y;

				if (current.position.Z < zmin)
					zmin = current.position.Z;
				else if (current.position.Z > zmax)
					zmax = current.position.Z;

				if (current.position.X < xmin)
					xmin = current.position.X;
				else if (current.position.X > xmax)
					xmax = current.position.X;
			}

			modelCenter = new Vector3(xmin + (xmax - xmin) / 2, ymin + (ymax - ymin) / 2, zmin + (zmax - zmin) / 2);
			eyePoint = new Vector3(Math.Abs(ymax - ymin) * 1.7f, 0, 0);

			device.Transform.Projection = Matrix.PerspectiveFovLH((float)Math.PI / 4, 1, 0.10f, 100f);
			device.Transform.View = Matrix.LookAtLH(eyePoint, new Vector3(0, 0, 0), new Vector3(0, 1, 0));
		}

		#endregion

		#region Helpers

		private void ReadMouse()
		{
			try
			{
				MouseState state = mouse.CurrentMouseState;
				byte[] buttonBuffer = state.GetMouseButtons();

				mouse.Poll();

				if (0 != buttonBuffer[0] && panelhover) RotateModel(state.X, state.Y); //lmb
				if (0 != buttonBuffer[1] && panelhover) Zoom(state.Y); //rmb
				if (state.Z != 0) { }; //wheel
			}
			catch (Microsoft.DirectX.DirectInput.InputLostException) { }
		}

		private void RecalculateNormals()
		{
			foreach (Face f in mesh.faces)
				f.ComputeNormal();

			foreach (Vertex v in mesh.vertices)
				v.ComputeNormal();
		}

		#endregion

		protected override void OnPaint(PaintEventArgs e)
		{
			ReadMouse();

			device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.White, 1.0f, 0);
			device.BeginScene();
			
			if (mesh == null)
			{
				device.EndScene();
				device.Present();
				
				this.sStripBottom.Refresh();
				Update();
				Invalidate();

				return;
			}

			device.Transform.World = Matrix.Translation(-modelCenter) * Matrix.RotationQuaternion(modelQuaternion);
			device.VertexFormat = CustomVertex.PositionNormal.Format;
			
			if (this.faces)
			{
				device.DrawUserPrimitives(PrimitiveType.TriangleList, facesCount, vertices);
			}

			if (this.displayOption != AdditionalDisplay.None)
			{
				if (this.displayOption == AdditionalDisplay.Points)
					device.RenderState.FillMode = FillMode.Point;
				else
					device.RenderState.FillMode = FillMode.WireFrame;

				device.RenderState.Lighting = false;
				device.DrawUserPrimitives(PrimitiveType.TriangleList, facesCount, vertices);

				device.RenderState.Lighting = true;
				device.RenderState.FillMode = FillMode.Solid;
			}

			//device.RenderState.Lighting = false;
			//device.VertexFormat = CustomVertex.PositionColored.Format;
			
			//device.DrawUserPrimitives(PrimitiveType.LineList, mesh.vertices.Count, normals);

			//device.RenderState.Lighting = true;

			device.EndScene();
			device.Present();
			
			this.sStripBottom.Refresh();
			Update();
			Invalidate();
		}

		#region EventHandlers

		#region Display options

		private void cbFaces_CheckedChanged(object sender, EventArgs e)
		{
			faces = cbFaces.Checked;
		}

		private void ddlDisplayOptions_SelectedIndexChanged(object sender, EventArgs e)
		{
			this.displayOption = (AdditionalDisplay)Enum.Parse(typeof(AdditionalDisplay), this.ddlDisplayOptions.SelectedItem.ToString(), true);
		}

		private void ddlShade_SelectedIndexChanged(object sender, EventArgs e)
		{
			ShadeMode oldMode = device.RenderState.ShadeMode;
			ShadeMode newMode = (ShadeMode)Enum.Parse(typeof(ShadeMode), ddlShade.SelectedItem.ToString(), true);

			if (oldMode != ShadeMode.Flat)
			{
				if (newMode == ShadeMode.Flat)
				{
					// Gouraud or Phong -> Flat
					// replace vertex normals with face normals.
					VertexDeclaration(true);
				}

				// Gouraud -> Phong or Phong to Gouraud (do nothing)
			}
			else
			{
				// Flat -> Phong or Gouraud or Flat
				// repace face normals with vertex normals
				if (newMode != ShadeMode.Flat)
					VertexDeclaration(false);
			}

			device.RenderState.ShadeMode = newMode;

		}

		private void cbSpecular_CheckedChanged(object sender, EventArgs e)
		{
			device.RenderState.SpecularEnable = cbSpecular.Checked;
		}

		#endregion

		#region Mesh tab

		private void bRefreshMeshes_Click(object sender, EventArgs e)
		{
			ServerDataService.ServerData service = new ServerDataService.ServerData();
			service.ListMeshFilesCompleted += (obj, arg) =>
				{
					this.lbMeshes.Items.Clear();
					this.lbMeshes.Items.AddRange(arg.Result);
					this.sbProgressBar.Style = ProgressBarStyle.Blocks;
				};

			this.sbProgressBar.Style = ProgressBarStyle.Marquee;
			service.ListMeshFilesAsync();
		}

		private void bGenerate_Click(object sender, EventArgs e)
		{
			int iterations;

			if (lbMeshes.SelectedIndex == -1 || !int.TryParse(tbIterations.Text, out iterations))
				return;

			GenerationService.Generation service = new GenerationService.Generation();
			service.GenerateProgressiveCompleted += (obj, arg) =>
				{
					tslTime.Text = "Time: " + arg.Result;
					this.sbGenerationProgressBar.Style = ProgressBarStyle.Blocks;
				};

			this.sbGenerationProgressBar.Style = ProgressBarStyle.Marquee;
			service.GenerateProgressiveAsync(lbMeshes.SelectedItem.ToString(), ddlAlgotithm.SelectedItem.ToString(), iterations);
		}

		#endregion

		private void button4_Click(object sender, EventArgs e)
		{
			int iterations = int.Parse(tbIterationsNubmer.Text);
			textBox4.Text = (int.Parse(textBox4.Text) + iterations).ToString();
			progressive.DoSplits(iterations);
			RecalculateNormals();
			VertexDeclaration(device.RenderState.ShadeMode == ShadeMode.Flat);

		}

		private void button3_Click(object sender, EventArgs e)
		{
			string time;
			int iterations = int.Parse(tbIterationsNubmer.Text);
			textBox4.Text = (int.Parse(textBox4.Text) - iterations).ToString();
			//QEMSimplifier melax = new QEMSimplifier();
			//string times;
			progressive.simplifier = new QEMSimplifier();
			progressive.Simplify(iterations, out time);
			//melax.Simplify(progressive, iterations, out times);
			RecalculateNormals();
			VertexDeclaration(device.RenderState.ShadeMode == ShadeMode.Flat);
		}

		private void bLoad_Click(object sender, EventArgs e)
		{
			this.progressive = ProgressiveMeshFile.LoadProgressive("turarura");
			this.mesh = this.progressive.mesh;

			RecalculateNormals();

			textBox4.Text = mesh.vertices.Count.ToString();

			CameraPositioning();
			VertexDeclaration(true);
		}

		private void bSave_Click(object sender, EventArgs e)
		{
			ProgressiveMeshFile.SaveProgressive(this.progressive, "turarura");
		}

		private void bLoadPLY_Click(object sender, EventArgs e)
		{
			//PLYMeshFile loader = new PLYMeshFile();
			//mesh = PLYMeshFile.LoadFromPLYFile("sphere.ply");
			this.progressive = new ProgressiveMesh(PLYMeshFile.LoadFromPLYFile("happy_vrip.ply"), 34800);
			this.mesh = this.progressive.mesh;

			RecalculateNormals();

			textBox4.Text = mesh.vertices.Count.ToString();

			CameraPositioning();
			VertexDeclaration(true);
		}

		private void bDownloadBase_Click(object sender, EventArgs e)
		{
			ProgressiveService.Progressive service = new ProgressiveService.Progressive();
			service.LoadMeshBaseCompleted += (obj, arg) => 
			{
				this.mesh = ProgressiveMeshFile.LoadMeshFromString(arg.Result);
				this.progressive = new ProgressiveMesh(this.mesh);

				RecalculateNormals();

				textBox4.Text = mesh.vertices.Count.ToString();

				CameraPositioning();
				VertexDeclaration(true);
				this.sbProgressBar.Style = ProgressBarStyle.Blocks;
			};

			this.sbProgressBar.Style = ProgressBarStyle.Marquee;
			service.LoadMeshBaseAsync("turarura");
		}

		private void bDownloadSplits_Click(object sender, EventArgs e)
		{
			ProgressiveService.Progressive service = new ProgressiveService.Progressive();
			service.LoadSplitsCompleted += (obj, arg) =>
				{
					this.progressive.splits =  arg.Result.ToList();
					this.downloadedSplits += this.progressive.splits.Count;
					this.progressive.DoSplits(this.progressive.splits.Count);

					RecalculateNormals();

					ResetView();
					VertexDeclaration(device.RenderState.ShadeMode == ShadeMode.Flat);
					this.sbProgressBar.Style = ProgressBarStyle.Blocks;
				};

			this.sbProgressBar.Style = ProgressBarStyle.Marquee;
			service.LoadSplitsAsync("turarura", this.downloadedSplits, 3000);
		}


		#region Melax tab

		private void bRefreshMelax_Click(object sender, EventArgs e)
		{
			ServerDataService.ServerData service = new ServerDataService.ServerData();
			service.ListOutFilesCompleted += (obj, arg) =>
				{
					this.lbMelax.Items.Clear();
					this.lbMelax.Items.AddRange(arg.Result);
					this.sbProgressBar.Style = ProgressBarStyle.Blocks;
				};

			this.sbProgressBar.Style = ProgressBarStyle.Marquee;
			service.ListOutFilesAsync("melax");
		}

		private void bLoadBaseMelax_Click(object sender, EventArgs e)
		{
			if (lbMelax.SelectedIndex == -1)
				return;

			ProgressiveService.Progressive service = new ProgressiveService.Progressive();
			service.LoadMeshBaseCompleted += (obj, arg) =>
			{
				this.mesh = ProgressiveMeshFile.LoadMeshFromString(arg.Result);
				this.progressive = new ProgressiveMesh(this.mesh);
				this.mesh.vertices.Sort((x, y) => Comparer.Default.Compare(x.vertexId, y.vertexId));

				RecalculateNormals();
				CameraPositioning();
				VertexDeclaration(true);

				this.sbProgressBar.Style = ProgressBarStyle.Blocks;
				this.downloadedSplits = 0;
				lVertMelax.Text = "Vertices: " + this.mesh.vertices.Count;
			};

			this.sbProgressBar.Style = ProgressBarStyle.Marquee;
			service.LoadMeshBaseAsync("ProgressiveOut/Melax/" + lbMelax.SelectedItem);
		}

		private void bLoadSplitMelax_Click(object sender, EventArgs e)
		{
			Stopwatch timer = new Stopwatch();
			int splits;

			if (!int.TryParse(tbSplitsMelax.Text, out splits))
				return;

			ProgressiveService.Progressive service = new ProgressiveService.Progressive();
			service.LoadSplitsCompleted += (obj, arg) =>
			{
				this.progressive.splits = arg.Result.ToList();
				this.downloadedSplits += this.progressive.splits.Count;
				timer.Start();
				this.progressive.mesh.vertices.Capacity += this.progressive.splits.Count;
				this.progressive.DoSplits(this.progressive.splits.Count);
				timer.Stop();
				string time = timer.Elapsed.ToString();
				this.tslTime.Text = time;
				RecalculateNormals();
				ResetView();
				VertexDeclaration(device.RenderState.ShadeMode == ShadeMode.Flat);

				this.sbProgressBar.Style = ProgressBarStyle.Blocks;
				lVertMelax.Text = "Vertices: " + this.mesh.vertices.Count;
			};

			this.sbProgressBar.Style = ProgressBarStyle.Marquee;
			service.LoadSplitsAsync("ProgressiveOut/Melax/" + lbMelax.SelectedItem, this.downloadedSplits, splits);
		}

		#endregion

		#region QEM tab

		private void bRefreshQEM_Click(object sender, EventArgs e)
		{
			ServerDataService.ServerData service = new ServerDataService.ServerData();
			service.ListOutFilesCompleted += (obj, arg) =>
			{
				this.lbQEM.Items.Clear();
				this.lbQEM.Items.AddRange(arg.Result);
				this.sbProgressBar.Style = ProgressBarStyle.Blocks;
			};

			this.sbProgressBar.Style = ProgressBarStyle.Marquee;
			service.ListOutFilesAsync("qem");
		}

		private void bLoadBaseQEM_Click(object sender, EventArgs e)
		{
			if (lbQEM.SelectedIndex == -1)
				return;

			ProgressiveService.Progressive service = new ProgressiveService.Progressive();
			service.LoadMeshBaseCompleted += (obj, arg) =>
			{
				this.mesh = ProgressiveMeshFile.LoadMeshFromString(arg.Result);
				this.progressive = new ProgressiveMesh(this.mesh);
				this.mesh.vertices.Sort((x, y) => Comparer.Default.Compare(x.vertexId, y.vertexId));
				RecalculateNormals();
				CameraPositioning();
				VertexDeclaration(true);

				this.sbProgressBar.Style = ProgressBarStyle.Blocks;
				this.downloadedSplits = 0;
				lVertQEM.Text = "Vertices: " + this.mesh.vertices.Count;
			};

			this.sbProgressBar.Style = ProgressBarStyle.Marquee;
			service.LoadMeshBaseAsync("ProgressiveOut/QEM/" + lbQEM.SelectedItem);
		}

		private void bLoadSplitQEM_Click(object sender, EventArgs e)
		{
			Stopwatch timer = new Stopwatch();
			int splits;

			if (!int.TryParse(tbSplitsQEM.Text, out splits))
				return;

			ProgressiveService.Progressive service = new ProgressiveService.Progressive();
			service.LoadSplitsCompleted += (obj, arg) =>
			{
				this.progressive.splits = arg.Result.ToList();
				this.downloadedSplits += this.progressive.splits.Count;

				timer.Start();
				this.progressive.mesh.vertices.Capacity += this.progressive.splits.Count;
				this.progressive.DoSplits(this.progressive.splits.Count);
				timer.Stop();
				string time = timer.Elapsed.ToString();
				this.tslTime.Text = time;
				RecalculateNormals();
				ResetView();
				VertexDeclaration(device.RenderState.ShadeMode == ShadeMode.Flat);

				this.sbProgressBar.Style = ProgressBarStyle.Blocks;
				lVertQEM.Text = "Vertices: " + this.mesh.vertices.Count;
			};

			this.sbProgressBar.Style = ProgressBarStyle.Marquee;
			service.LoadSplitsAsync("ProgressiveOut/QEM/" + lbQEM.SelectedItem, this.downloadedSplits, splits);
		}

		#endregion

		#region Greedy tab

		private void bRefreshGreedy_Click(object sender, EventArgs e)
		{
			ServerDataService.ServerData service = new ServerDataService.ServerData();
			service.ListOutFilesCompleted += (obj, arg) =>
			{
				this.lbGreedy.Items.Clear();
				this.lbGreedy.Items.AddRange(arg.Result);
				this.sbProgressBar.Style = ProgressBarStyle.Blocks;
			};

			this.sbProgressBar.Style = ProgressBarStyle.Marquee;
			service.ListOutFilesAsync("greedy");
		}

		private void bLoadBaseGreedy_Click(object sender, EventArgs e)
		{
			if (lbGreedy.SelectedIndex == -1)
				return;

			ProgressiveService.Progressive service = new ProgressiveService.Progressive();
			service.LoadMeshBaseCompleted += (obj, arg) =>
			{
				this.mesh = ProgressiveMeshFile.LoadMeshFromString(arg.Result);
				this.progressive = new ProgressiveMesh(this.mesh);
				this.mesh.vertices.Sort((x, y) => Comparer.Default.Compare(x.vertexId, y.vertexId));
				RecalculateNormals();
				CameraPositioning();
				VertexDeclaration(true);

				this.sbProgressBar.Style = ProgressBarStyle.Blocks;
				this.downloadedSplits = 0;
				lVertGreedy.Text = "Vertices: " + this.mesh.vertices.Count;
			};

			this.sbProgressBar.Style = ProgressBarStyle.Marquee;
			service.LoadMeshBaseAsync("ProgressiveOut/Greedy/" + lbGreedy.SelectedItem);
		}

		private void bLoadSplitGreedy_Click(object sender, EventArgs e)
		{
			Stopwatch timer = new Stopwatch();
			int splits;

			if (!int.TryParse(tbSplitsGreedy.Text, out splits))
				return;

			ProgressiveService.Progressive service = new ProgressiveService.Progressive();
			service.LoadSplitsCompleted += (obj, arg) =>
			{
				this.progressive.splits = arg.Result.ToList();
				this.downloadedSplits += this.progressive.splits.Count;
				timer.Start();
				this.progressive.mesh.vertices.Capacity += this.progressive.splits.Count;
				this.progressive.DoSplits(this.progressive.splits.Count);
				timer.Stop();
				string time = timer.Elapsed.ToString();
				this.tslTime.Text = time;
				RecalculateNormals();
				ResetView();
				VertexDeclaration(device.RenderState.ShadeMode == ShadeMode.Flat);

				this.sbProgressBar.Style = ProgressBarStyle.Blocks;
				lVertGreedy.Text = "Vertices: " + this.mesh.vertices.Count;
			};

			this.sbProgressBar.Style = ProgressBarStyle.Marquee;
			service.LoadSplitsAsync("ProgressiveOut/Greedy/" + lbGreedy.SelectedItem, this.downloadedSplits, splits);
		}

		#endregion

		#endregion


	}
}
